package com.atguigu.tingshu.user.service.impl;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import com.atguigu.tingshu.album.AlbumFeignClient;
import com.atguigu.tingshu.common.constant.KafkaConstant;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.service.KafkaService;
import com.atguigu.tingshu.common.util.AuthContextHolder;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.model.user.*;
import com.atguigu.tingshu.user.mapper.*;
import com.atguigu.tingshu.user.service.UserInfoService;
import com.atguigu.tingshu.user.strategy.ItemTypeStrategy;
import com.atguigu.tingshu.user.strategy.StrategyFactory;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import com.atguigu.tingshu.vo.user.UserPaidRecordVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;

@Slf4j
@Service
@SuppressWarnings({"all"})
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService {

	@Autowired
	private UserInfoMapper userInfoMapper;

	@Autowired
	private WxMaService wxMaService;

	@Autowired
	private RedisTemplate redisTemplate;

	@Autowired
	private KafkaService kafkaService;

	@Autowired
	private UserPaidAlbumMapper userPaidAlbumMapper;

	@Autowired
	private UserPaidTrackMapper userPaidTrackMapper;

	@Autowired
	private AlbumFeignClient albumFeignClient;

	@Autowired
	private VipServiceConfigMapper vipServiceConfigMapper;

	@Autowired
	private UserVipServiceMapper userVipServiceMapper;

	@Autowired
	private StrategyFactory strategyFactory;

	/**
	 * 小程序端提交临时凭据code，登录（调用微信接口获取微信账号唯一标识：openId）
	 *
	 * @param code 临时凭据
	 * @return 对象，登录登录成功后：token
	 */
	@Override
	public Map<String, String> wxLogin(String code) {

		try {
			//1.根据入参提交临时凭据code，调用微信获取微信账户唯一标识接口，得到微信账户openId
			WxMaJscode2SessionResult sessionInfo = wxMaService.getUserService().getSessionInfo(code);

			if (sessionInfo != null){

				//拿到微信接口返回的openid，根据openid查询用户数据，如果没查到证明时第一次登录则注册
				String wxOpenId = sessionInfo.getOpenid();

				UserInfo userInfo = userInfoMapper.selectOne(new LambdaQueryWrapper<UserInfo>().eq(UserInfo::getWxOpenId, wxOpenId));

				//判断是否是第一次登录，第一次则注册
				if (userInfo == null){
	//				构建用户对象，保存用户记录
					userInfo = new UserInfo();
					userInfo.setWxOpenId(wxOpenId);
					userInfo.setNickname("听友" + IdUtil.getSnowflakeNextId());
					userInfo.setAvatarUrl("https://oss.aliyuncs.com/aliyun_id_photo_bucket/default_handsome.jpg");
					userInfo.setIsVip(0);
					userInfoMapper.insert(userInfo);

					//初始化用户账户信息 --->  发送Kafka异步消息，通知账户微服务新增账户记录
					kafkaService.sendMessage(KafkaConstant.QUEUE_USER_REGISTER, userInfo.getId().toString());

				}

				//不是第一次登录 或者第一次登陆注册完成了 基于用户记录生成Token 将用户令牌存入Redis Key:前缀+token  Value:用户信息UserInfoVo
				String token = IdUtil.fastUUID();
				String loginKey = RedisConstant.USER_LOGIN_KEY_PREFIX + token;

				//排除掉用户隐私数据
				UserInfoVo userInfoVo = BeanUtil.copyProperties(userInfo, UserInfoVo.class);

				//将token和用户数据存到Redis
				redisTemplate.opsForValue().set(loginKey, userInfoVo, RedisConstant.USER_LOGIN_KEY_TIMEOUT, TimeUnit.SECONDS);

				//将用户token封装结果返回数据
				Map<String, String> mapResult = new HashMap<>();
				mapResult.put("token", token);
				return  mapResult;
			}
		} catch (Exception e) {
			log.error("[用户服务]微信登录异常：{}", e);
			throw new RuntimeException(e);
		}

		return null;
	}

	/**
	 * 查询用户基本信息
	 *
	 * @param userId
	 * @return
	 */
	@Override
	public UserInfoVo getUserInfo(Long userId) {
		//1.根据主键ID查询用户对象
		UserInfo userInfo = userInfoMapper.selectById(userId);
		//2.将用户PO对象转为VO对象
		return BeanUtil.copyProperties(userInfo, UserInfoVo.class);
	}

	/**
	 * 修改用户基本信息（限定只能修改账户昵称、头像）
	 *
	 * @param userId
	 * @param userInfoVo
	 */
	@Override
	public void updateUser(Long userId, UserInfoVo userInfoVo) {
		UserInfo userInfo = new UserInfo();
		userInfo.setId(userId);
		userInfo.setNickname(userInfoVo.getNickname());
		userInfo.setAvatarUrl(userInfoVo.getAvatarUrl());
		userInfoMapper.updateById(userInfo);
	}

	/**
	 * 根据用户ID获取用户（主播）基本信息
	 *
	 * @param userId
	 * @return
	 */
	@Override
	public UserInfoVo getUserInfoVoByUserId(Long userId) {
		//2.根据用户ID查询用户记录UserInfo
		UserInfo userInfo = userInfoMapper.selectById(userId);
		//3.转为UserInfoVo返回
		return BeanUtil.copyProperties(userInfo, UserInfoVo.class);
	}

	/**
	 * 判断当前用户某一页中声音列表购买情况
	 *
	 * @param userId               用户ID
	 * @param albumId              专辑ID
	 * @param needChackTrackIdList 待检查购买情况声音列表
	 * @return data:{声音ID：购买结果}   结果：1（已购）0（未购买）
	 */
	@Override
	public Map<Long, Integer> userIsPaidTrack(Long userId, Long albumId, List<Long> needChackTrackIdList) {

		//创建封装结果的Map
		Map<Long, Integer> mapResult = new HashMap<>();

		//根据专辑id和用户id查询专辑购买记录表
		Long count = userPaidAlbumMapper.selectCount(new LambdaQueryWrapper<UserPaidAlbum>()
				.eq(UserPaidAlbum::getUserId, userId).eq(UserPaidAlbum::getAlbumId, albumId));

		//如果该用户已购买该专辑id（所有声音也已购买）  则所有声音都可播放 值设为1
		if (count > 0){
			for (Long trackId : needChackTrackIdList) {
				mapResult.put(trackId, 1);
			}
			return mapResult;
		}

		//如果该用户没购买该专辑，则查询该用户是否购买该专辑下的声音 根据用户id和声音集合id 查询声音购买记录表
		List<UserPaidTrack> userPaidTracks = userPaidTrackMapper.selectList(new LambdaQueryWrapper<UserPaidTrack>()
				.eq(UserPaidTrack::getUserId, userId).in(UserPaidTrack::getTrackId, needChackTrackIdList));
		//没查到则声音都没购买 值设为0
		if (CollectionUtil.isEmpty(userPaidTracks)){
			for (Long trackId : needChackTrackIdList) {
				mapResult.put(trackId, 0);
			}
			return mapResult;
		}

		//查到了，查到有的id设为1 没有的设为0
		List<Object> userPaidTrackIdList = userPaidTracks.stream()
				.map(UserPaidTrack::getTrackId).collect(Collectors.toList());

		for (Long needCheckTrackId : needChackTrackIdList) {

			if (userPaidTrackIdList.contains(needCheckTrackId)){
				//如果待检查声音ID包含在已购声音Id集合中（已购买）
				mapResult.put(needCheckTrackId, 1);
			}else {
				//反之则未购买声音
				mapResult.put(needCheckTrackId, 0);
			}

		}

		return mapResult;
	}

	/**
	 * 验证当前用户是否购买过专辑
	 *
	 * @param albumId
	 * @return
	 */
	@Override
	public Boolean isPaidAlbum(Long albumId) {
		//1.获取当前用户ID
		Long userId = AuthContextHolder.getUserId();
		//2.构建查询条件：用户ID+专辑ID 查询专辑购买记录表
		LambdaQueryWrapper<UserPaidAlbum> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.eq(UserPaidAlbum::getUserId, userId);
		queryWrapper.eq(UserPaidAlbum::getAlbumId, albumId);
		Long count = userPaidAlbumMapper.selectCount(queryWrapper);
		return count > 0;
	}

	/**
	 * 根据用户ID+专辑ID查询已购声音集合
	 *
	 * @param userId  用户ID
	 * @param albumId 专辑ID
	 * @return
	 */
	@Override
	public List<Long> getUserPaidTrackIdList(Long userId, Long albumId) {
		//1.根据用户ID+专辑ID查询已购声音集合
		LambdaQueryWrapper<UserPaidTrack> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.eq(UserPaidTrack::getUserId, userId);
		queryWrapper.eq(UserPaidTrack::getAlbumId, albumId);
		List<UserPaidTrack> userPaidTrackList = userPaidTrackMapper.selectList(queryWrapper);
		if (CollectionUtil.isNotEmpty(userPaidTrackList)) {
			//2.获取已购声音ID集合
			List<Long> userPaidTrackIdList = userPaidTrackList.stream()
					.map(UserPaidTrack::getTrackId).collect(Collectors.toList());
			return userPaidTrackIdList;
		}
		return null;
	}


	/**
	 * 处理用户购买记录（虚拟物品发货）
	 *
	 * userPaidRecordVo.getItemType()  1001  1002  1003
	 * @param userPaidRecordVo 购买记录VO
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void savePaidRecord(UserPaidRecordVo userPaidRecordVo) {


		//使用策略模式优化代码
		//获取购买类型
		String itemType = userPaidRecordVo.getItemType();
		//从策略工厂中获取对应的策略对象
		ItemTypeStrategy strategy = strategyFactory.getStrategy(itemType);
		//执行策略对象的任务
		strategy.savePaidRecord(userPaidRecordVo);


//		if (SystemConstant.ORDER_ITEM_TYPE_ALBUM.equals(userPaidRecordVo.getItemType())) {
//			//1.判断购买项目类型-处理专辑
//			//1.1 根据订单编号查询专辑购买记录  -- 防止订单模块重复调用Feign重复新增购买记录
//			LambdaQueryWrapper<UserPaidAlbum> userPaidAlbumLambdaQueryWrapper = new LambdaQueryWrapper<>();
//			userPaidAlbumLambdaQueryWrapper.eq(UserPaidAlbum::getOrderNo, userPaidRecordVo.getOrderNo());
//			Long count = userPaidAlbumMapper.selectCount(userPaidAlbumLambdaQueryWrapper);
//			if (count > 0) {
//				return;
//			}
//			//1.2 查询到专辑购买记录为空则新增购买记录
//			UserPaidAlbum userPaidAlbum = new UserPaidAlbum();
//			userPaidAlbum.setOrderNo(userPaidRecordVo.getOrderNo());
//			userPaidAlbum.setUserId(userPaidRecordVo.getUserId());
//			userPaidAlbum.setAlbumId(userPaidRecordVo.getItemIdList().get(0));
//			userPaidAlbumMapper.insert(userPaidAlbum);
//		} else if (SystemConstant.ORDER_ITEM_TYPE_TRACK.equals(userPaidRecordVo.getItemType())) {
//			//2.判断购买项目类型-处理声音
//			//2.1 根据订单编号查询声音购买记录
//			LambdaQueryWrapper<UserPaidTrack> userPaidTrackLambdaQueryWrapper = new LambdaQueryWrapper<>();
//			userPaidTrackLambdaQueryWrapper.eq(UserPaidTrack::getOrderNo, userPaidRecordVo.getOrderNo());
//			Long count = userPaidTrackMapper.selectCount(userPaidTrackLambdaQueryWrapper);
//			if (count > 0) {
//				return;
//			}
//			//2.2 查询到声音购买记录为空则新增购买记录（循环批量新增）
//			//2.2.1 远程调用专辑服务-根据声音ID查询声音对象-获取声音所属专辑ID
//			TrackInfo trackInfo = albumFeignClient.getTrackInfo(userPaidRecordVo.getItemIdList().get(0)).getData();
//			Long albumId = trackInfo.getAlbumId();
//			//2.2.2 遍历购买项目ID集合批量新增声音购买记录
//			userPaidRecordVo.getItemIdList().forEach(trackId -> {
//				UserPaidTrack userPaidTrack = new UserPaidTrack();
//				userPaidTrack.setOrderNo(userPaidRecordVo.getOrderNo());
//				userPaidTrack.setUserId(userPaidRecordVo.getUserId());
//				userPaidTrack.setAlbumId(albumId);
//				userPaidTrack.setTrackId(trackId);
//				userPaidTrackMapper.insert(userPaidTrack);
//			});
//		} else if (SystemConstant.ORDER_ITEM_TYPE_VIP.equals(userPaidRecordVo.getItemType())) {
//			//3.判断购买项目类型-处理VIP会员-允许多次购买
//			//防止重复处理vip
//			Long count = userVipServiceMapper.selectCount(new LambdaQueryWrapper<UserVipService>()
//					.eq(UserVipService::getOrderNo, userPaidRecordVo.getOrderNo()));
//			if (count > 0) {
//				return;
//			}
//
//			//3.1 新增VIP购买记录
//			UserVipService userVipService = new UserVipService();
//			//3.1.1 根据VIP套餐ID查询套餐信息-得到VIP会员服务月数
//			Long vipConfigId = userPaidRecordVo.getItemIdList().get(0);
//			VipServiceConfig vipServiceConfig = vipServiceConfigMapper.selectById(vipConfigId);
//			Integer serviceMonth = vipServiceConfig.getServiceMonth();
//			//3.1.2 获取用户身份，如果是VIP会员，则续费
//			UserInfo userInfo = userInfoMapper.selectById(userPaidRecordVo.getUserId());
//			Integer isVip = userInfo.getIsVip();
//			if (isVip.intValue() == 1 && userInfo.getVipExpireTime().after(new Date())) {
//				//如果是VIP会员，则续费
//				userVipService.setStartTime(userInfo.getVipExpireTime());
//				//续费会员过期时间=现有会员过期时间+套餐服务月数
//				userVipService.setExpireTime(DateUtil.offsetMonth(userInfo.getVipExpireTime(), serviceMonth));
//			} else {
//				//3.1.3 获取用户身份，如果是普通用户，则新开
//				userVipService.setStartTime(new Date());
//				//续费会员过期时间=现有会员过期时间+套餐服务月数
//				userVipService.setExpireTime(DateUtil.offsetMonth(new Date(), serviceMonth));
//			}
//			//3.1.4 构建VIP购买记录对象保存
//			userVipService.setUserId(userPaidRecordVo.getUserId());
//			userVipService.setOrderNo(userPaidRecordVo.getOrderNo());
//			userVipServiceMapper.insert(userVipService);
//
//			//3.2 更新用户表中VIP状态及会员过期时间
//			userInfo.setIsVip(1);
//			userInfo.setVipExpireTime(userVipService.getExpireTime());
//			userInfoMapper.updateById(userInfo);
//		}
	}


	/**
	 * 更新Vip到期失效状态
	 *
	 * @return
	 */
	@Override
	public void updateVipExpireStatus() {
		//1.已经过期会员
		LambdaQueryWrapper<UserInfo> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.eq(UserInfo::getIsVip, "1");
		queryWrapper.lt(UserInfo::getVipExpireTime, DateUtil.beginOfDay(new Date()));
		//查询
		List<UserInfo> list = userInfoMapper.selectList(queryWrapper);
		//2.批量更新
		if (CollectionUtil.isNotEmpty(list)) {
			List<UserInfo> collect = list.stream().map(userInfo -> {
				UserInfo userInfo1 = new UserInfo();
				userInfo1.setIsVip(0);
				userInfo1.setId(userInfo.getId());
				return userInfo1;
			}).collect(Collectors.toList());
			this.updateBatchById(collect);
		}
	}


}
